<script>
  import DictRender from '@/components/table/DictRender.vue'
  import { flatArray } from '@/util/core'

  const tableColumnProps = {
    props: {
      type: {
        type: String,
        default: 'default'
      },
      label: String,
      className: String,
      labelClassName: String,
      property: String,
      prop: String,
      width: {},
      minWidth: {},
      renderHeader: Function,
      sortable: {
        type: [Boolean, String],
        default: true
      },
      sortMethod: Function,
      sortBy: [String, Function, Array],
      resizable: {
        type: Boolean,
        default: true
      },
      columnKey: String,
      align: String,
      headerAlign: String,
      showTooltipWhenOverflow: Boolean,
      clickable: Boolean,
      cellClick: Function,
      showOverflowTooltip: {
        type: Boolean,
        default: true
      },
      fixed: [Boolean, String],
      formatter: Function,
      selectable: Function,
      reserveSelection: Boolean,
      filterMethod: Function,
      filteredValue: Array,
      filters: Array,
      filterPlacement: String,
      filterMultiple: {
        type: Boolean,
        default: true
      },
      index: [Number, Function],
      sortOrders: {
        type: Array,
        default() {
          return ['ascending', 'descending', null]
        },
        validator(val) {
          return val.every(order => ['ascending', 'descending', null].indexOf(order) > -1)
        }
      },
      dictType: String,
      options: Array,
      autoUpdate: Boolean
    }
  }

  const builtInColumns = ['selection', 'single-selection', 'index', 'expand']

  function cellClickHandler(parent, row, column, cell, e) {
    const rowDbClick = parent.rowDbClick || parent.$children.find(value => value.$options.name === 'TableView')?.rowDbClick
    rowDbClick?.(row, column, cell, e)
  }

  const getCell = event => {
    let cell = event.target

    while (cell && cell.tagName.toUpperCase() !== 'HTML') {
      if (cell.tagName.toUpperCase() === 'TD') {
        return cell
      }
      cell = cell.parentNode
    }

    return null
  }

  const isEmpty = array => !flatArray(array).length

  export default {
    name: 'TableColumn',
    functional: true,
    mixins: [tableColumnProps],
    render(createElement, { data, props, children, parent, listeners: { click } }) {
      let { scopedSlots, ...rest } = data

      const { clickable, cellClick, ...properties } = props

      const isClickable = clickable || click || cellClick

      // 可点击或者是使用的字典的列
      if (isClickable || props.dictType || props.options) {
        scopedSlots = { ...(scopedSlots || {}) }

        const defaultSlot = scopedSlots.default

        scopedSlots.default = cellProps => {
          if (builtInColumns.includes(cellProps.type)) {
            return defaultSlot(cellProps)
          } else {
            const { row, column } = cellProps

            const clickHandler = e => {
              const cell = getCell(e)

              if (click || cellClick) {
                click?.(row, column, row, column, cell, e)
                cellClick?.(row, column, row, column, cell, e)
              } else {
                cellClickHandler(parent, row, column, cell, e)
              }
            }

            let vNodes = defaultSlot?.(cellProps)

            if (isEmpty(vNodes) && children?.length) {
              vNodes = children
            }

            if (isEmpty(vNodes)) {
              vNodes = null
            }

            return (props.dictType || props.options) && !vNodes ? (
              <DictRender
                class={{ 'is-clickable': isClickable }}
                onClick={clickHandler}
                row={row}
                column={column}
                dictType={props.dictType}
                options={props.options}
              />
            ) : isClickable ? (
              <span class="is-clickable" onClick={clickHandler}>
                {vNodes || row[column.property]}
              </span>
            ) : (
              vNodes
            )
          }
        }
      } else {
        if (children && !scopedSlots?.default) {
          scopedSlots = { ...(scopedSlots || {}) }
          scopedSlots.default = () => children
        }
      }

      const attrs = {
        ...rest,
        props: {
          ...properties,
          showOverflowTooltip: builtInColumns.includes(properties.type) ? false : properties.showOverflowTooltip
        }
      }

      return <ElTableColumn {...attrs} scopedSlots={scopedSlots} />
    }
  }
</script>

<style lang="scss">
  .is-clickable {
    text-decoration: underline;
    cursor: pointer;

    &:hover {
      color: var(--color-primary);
    }
  }

  .el-table__column-filter-trigger {
    line-height: unset;
  }
</style>